/**
 * @file header file for functions for computations over a skew polynomial ring
 */


#ifndef SQ_RING_H
#define SQ_RING_H


// include the NTL library, visit http://www.shoup.net/ntl/
#include <NTL/ZZ_pXFactoring.h>
#include <NTL/ZZ_pEX.h>
NTL_CLIENT


#define PRIMITIVE_ELEMENT_FILENAME "primitive_element.ntl"

/**
 * finds and returns the weight (i.e. number of non-zero elements) in a SQ polynomial
 *
 **/
int coeff_weight(const ZZ_pEX& );

/**
 * finds and returns the weight (i.e. number of non-zero elements) in a vector in GF(q)
 * 
 **/
int coeff_weight(const vec_ZZ_pE& );


/**
 *   Finds the Frobenius Automorphism of an element
 *
 *   @a the element for which the mapping is done
 *   @p the characteristic of the base field
 *   @i the iterations of the mapping
 *
 *   @return outputs \sigma_{p}^{i}(a)=a^(p^i) 
 **/
ZZ_pE	FAuto_p(const ZZ_pE& a,ZZ p,long i);

/**
 * (r)ight (mul)tiplies the first input skew polynomial by the second input skew polynomial.
 *
 * In this function, the Frobenius Automorphism is assumed over the skew ring.
 *
 * @a the first input polynomial in the pre-defined skew polynomial ring
 * @b the second input polynomial in the pre-defined skew polynomial ring
 *
 **/
ZZ_pEX	SQ_mulr(const ZZ_pEX& a, const ZZ_pEX& b);

/**
 * (r)ight (mul)tiplies the input skew polynomial by the input (const)ant. 
 *
 * In this function, the Frobenius Automorphism is assumed over the skew ring.
 *
 * @a input polynomial from the defined skew polynomial ring
 * @b input constant element from the same ring
 *
 **/
ZZ_pEX SQ_mulr_const(ZZ_pEX a,const ZZ_pE& b);

/**
 * (r)ight (div)ides the first skew polynomial input by the right skew polynomial input.
 *
 * In this function, the Frobenius Automorphism is assumed over the skew ring.
 *
 * @a input polynomial from the defined skew polynomial ring
 * @b input constant element from the same ring
 * @Q the quotien passed back by reference
 * @R the residue passed back by reference
 *
 **/
void SQ_divr(const ZZ_pEX& f,const ZZ_pEX& g,ZZ_pEX& Q,ZZ_pEX& R);

/**
 * (l)eft (div)ides the first skew polynomial input by the second skew polynomial input, i.e. f=gQ+R
 *
 * In this function, the Frobenius Automorphism is assumed over the skew ring.
 *
 * @f input polynomial from the defined skew polynomial ring
 * @g input constant element from the same ring
 * @Q the quotien passed back by reference
 * @R the residue passed back by reference
 *
 **/
void SQ_divl(const ZZ_pEX& f,const ZZ_pEX& g,ZZ_pEX& Q,ZZ_pEX& R);

/**
 * finds r'th inverse automorphism of an element
 *
 * This function asumes Frobenius Automorphism and returns \theta^{-r}(a)
 *
 * @a arbitrary element in the extension field
 * @r multiplicity of inverse
 *
 * @return returns r'th inverse automorphism of a
 *
 **/
ZZ_pE SQ_invAuto(const ZZ_pE& a,long r);


/**
 * finds (g)reatest (c)ommon (r)ight (d)ivisor of the input polynomials over the skew polynomial ring
 *
 * @f_1 first input skew polynomial
 * @f_2 second input skew polynomial
 *
 * @return the gcrd
 *
 **/
ZZ_pEX SQ_gcrd(const ZZ_pEX& f_1,const ZZ_pEX& f_2);


/**
 * Computes a polynomial raised to the input power (inefficient)
 *
 * @poly input skew polynomial
 * @exp the power to which the polynomial will be raised
 *
 * @return polynomial raised to the given power
 *
 **/
ZZ_pEX SQ_power(const ZZ_pEX& poly,int exp);


#endif
